<template>
  <div class="goods-sku">
    <dl v-for="(item, index) in goods.specs" :key="index">
      <dt>{{ item.name }}</dt>
      <dd>
        <!-- disabled:禁用  selected:选中 -->
        <template v-for="(i, index2) in item.values" :key="index2">
          <img
            :title="i.name"
            v-if="i.picture"
            :class="{ selected: i.selected, disabled: i.disabled }"
            :src="i.picture"
            alt=""
            @click="itemClick(i, item.values)"
          />
          <span
            :class="{ selected: i.selected, disabled: i.disabled }"
            v-else
            @click="itemClick(i, item.values)"
            >{{ i.name }}</span
          >
        </template>
      </dd>
    </dl>
  </div>
</template>
<script>
/*
数组字典处理过程
1:拿到有效商品sku属性数组
2：通过算法算出所有的组合集
3：将组合集转换成对象供后续使用
*/
// 数组字典处理过程
import btPowerSet from '@/vender/btPowerSet'
function getPathMap (skus) {
  const pathMap = {}
  const str = '##'
  // sku属性集循环
  skus.forEach(item => {
    // 有货的sku
    if (item.inventory) {
      // item.specs.map(item2 => item2.valueName):将有货的sku属性集转换成属性集数组
      const _arr = btPowerSet(item.specs.map(item2 => item2.valueName)) // [蓝色，中国，20cm]
      // _arr:属性集产生的所有组合属性，它是一个数组
      _arr.forEach(i => {
        // 将数组转换成一个字符串，该字符串是一个对象的key,都加入到一个对象，供后续方便使用
        pathMap[i.join(str)] = true
      })
    }
  })
  return pathMap
  // console.log(pathMap)
}
/*   
默认禁用选择处理
1:拿到每一个对应商品属性去数据字典查询 ，如果它的值为undefined,说明没货
2：在属性对象加入disabled属性，如果有货它的值为false,没货就是true
3:将该属性应用到页面上
选择某属性后再次进行是否禁用判断
1:拿到已选择商品属性，而且该属性是一个数组，有选择就是相应属性名，没选择就是undefined
2:在更新按钮禁用状态方法中加入已选择处理

*/
function updateDisabledState (goods, pathMap) {
  // console.log(goods, 'goods')
  goods.specs.forEach((item, index) => {
    // 获取已选择属性数组
    const _selectArr = getSelected(goods)
    item.values.forEach(item2 => {
      // 没选择时默认是否禁用
      // item2.disabled = !pathMap[item2.name]
      if (_selectArr[index] === item2.name) {
        // 已选择按钮就不用判断
        return
      } else {
        // 没有选择的其它按钮就需要做相应判断
        // 首先默认该属性已选择
        _selectArr[index] = item2.name // 【黑色，中国，undefined】
        // 去掉undefined项，将属性转换成字符串，方便后面去数据字典查询
        const _key = _selectArr.filter(v => v).join('##') // [黑色， 中国]==>黑色##中国
        // console.log('key:', _key)
        // 去数据字典查询 该属性，如果该属性存在，说明有货，让item2.disabled为false,没货就是true
        item2.disabled = !pathMap[_key]
      }
    })
  })
}
// 拿到已选择商品属性
function getSelected (goods) {
  const _arr = []
  goods.specs.forEach((item, index) => {
    // 循环属性集数组，进行find查找 ，如果属性中有selected:true,就取出该项
    const _temp = item.values.find(item2 => item2.selected)
    // 如果找出已选择项，我们只要它的name,没找到就是undefined
    _arr[index] = _temp ? _temp.name : undefined
  })
  // console.log('已选择属性', _arr)
  return _arr
}
// 父组件传入skuid，子组件选择该skuid对应属性
/*
父组件传入skuid，子组件选择该skuid对应属性
1:找到该skuid对应的数据
2：通过找到的数据拿到属性集
3：在数据渲染的属性中进行匹配，匹配到了就selected:true
*/

function initSelected (goods, skuId) {
  // 通过对sku集合进行查找 找到对应skuid的项
  let _result = goods.skus.find(item => item.id === skuId)
  // 如果找到了
  if (_result) {
    // 取出找到的项对应的属性集合
    const _resultArr = _result.specs.map(item => item.valueName) // [黑色，中国，10cm]
    // console.log('_resultArr', _resultArr)
    // 对页面渲染的属性做循环判断
    goods.specs.forEach(item => {
      // item.name在_resultArr中是否存在 存在  item.selected=true 不存在 item.selected=true
      item.values.forEach(item2 => {
        // 如果渲染的属性它在前面获取的sku对应的属性集中存在，说明要选中,不存在就不选中
        item2.selected = _resultArr.includes(item2.name)
      })
    })
  }
}
/*

当选择完成后，通知父组件已选择项对应的skuid,如果没选择完成，父组件只能拿到空字符串
1：拿到已选择商品属性   [蓝色 日本  30cm]
2：通过已选择属性确定对应的skuid         
   skus  specs valueName转换成字符串
   拿到已选择商品属性也转换成字符串

*/
function getSlecectedSkuid (goods, emit) {
  // 确定是否选择完成，没选择完成，不理，选择完成通知父组件
  const _arr = getSelected(goods).filter(v => v)
  if (_arr.length === goods.specs.length) {
    // 属性选择完成
    const _result = goods.skus.find(item => {
      const _temp = item.specs.map(item2 => item2.valueName).join('##') // "蓝色##日本##30cm"
      // "蓝色##日本##30cm"
      return _temp === _arr.join('##')
    })
    if (_result) {
      emit('getSkuId', _result)
    }
    // console.log('找到的skuid结果:', _result)
  } else {
    // 如果没选择完成，通知父组件数据要清空
    emit('getSkuId', {})
  }
}

export default {
  name: 'GoodsSku',
  props: {
    goods: {
      type: Object,
      default: () => {}
    },
    skuId: {
      type: String,
      default: '1369155865461919746'
    }
  },
  setup (props, { emit }) {
    // 拿到数据字典供后面使用
    const pathMap = getPathMap(props.goods.skus)
    // 默认禁用处理
    updateDisabledState(props.goods, pathMap)
    // 选中效果处理
    function itemClick (item, itemArr) {
      if (item.disabled) {
        return
      }
      //   如果选中了某个属性，同类其它属性都要取消选择
      if (!item.selected) {
        itemArr.forEach(element => {
          element.selected = false
        })
      }
      item.selected = !item.selected
      // 选择后的禁用处理
      updateDisabledState(props.goods, pathMap)
      // 选择属性后通知父组件
      getSlecectedSkuid(props.goods, emit)
    }

    // 如果skuid存在就默认选中对应属性
    initSelected(props.goods, props.skuId)
    return { itemClick }
  }
}
</script>
<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      color: #666;
      > img {
        width: 50px;
        height: 50px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 28px;
        padding: 0 20px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
